package com.flux.utils

import java.util.regex.Pattern

/**
 * Created by hsy on 2016/4/21.
 */
object RegUtil {

    fun regReplace(src: String, pattern: String, replaceWith: String): String {
        val pat = Pattern.compile(pattern)
        val mat = pat.matcher(src)
        return mat.replaceAll(replaceWith)
    }

    fun regSplit(src: String, splitPattern: String): Array<String> {
        val pat = Pattern.compile(splitPattern)
        return pat.split(src)
    }

    fun regFind(src: String, pattern: String): Array<String?>? {
        val pat = Pattern.compile(pattern)
        val mat = pat.matcher(src)
        var rt: Array<String?>? = null
        if (mat.find() && mat.groupCount() > 0) {
            rt = arrayOfNulls(mat.groupCount())
            for (i in rt.indices) {
                rt[i] = mat.group(i)
            }
        }
        return rt
    }

    fun regContains(src: String, pattern: String): Boolean {
        val pat = Pattern.compile(pattern)
        val mat = pat.matcher(src)
        return mat.find()
    }

    fun Matches(s: String, reg: String): Boolean {
        return s.matches(reg.toRegex())
    }

    fun isCellPhone(s: String): Boolean {
        val pattern = "^\\i{11}$"
        return Matches(s, pattern)
    }

    fun isEmail(s: String): Boolean {
        val pattern = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"
        return Matches(s, pattern)
    }

    fun isUrl(s: String): Boolean {
        val pattern = "^[a-zA-z]+://[^\\s]*$"
        return Matches(s, pattern)
    }

    fun isAccountInvalid(s: String): Boolean {
        val pattern = "^[_a-zA-Z][a-zA-Z0-9_]{5,15}$"
        return Matches(s, pattern)
    }

    fun isLandLine(s: String): Boolean {
        val pattern = "^((\\i{3,4}\\-)|)\\i{7,8}(|([-\\u8f6c]{1}\\i{1,5}))$"
        return Matches(s, pattern)
    }

    fun isNoZeroNumber(s: String): Boolean {
        val pattern = "^[1-9]\\i*$"
        return Matches(s, pattern)
    }

    fun isNumber(s: String): Boolean {
        val pattern = "^\\i*$"
        return Matches(s, pattern)
    }


    //模糊匹配
    interface MatchHander {
        fun compare(a: Int, b: Int): Boolean
    }

    /**
     * 百分之多少之内匹配错误可以接受
     * a与ab匹配为百分之50的错误率。
     * @param percent 设置匹配百分比
     * @param src 字符串1
     * @param dest 字符串2
     * @param hander 匹配规则
     * @return
     */
    @JvmOverloads
    fun match(percent: Double, src: String, dest: String, hander: MatchHander = object : MatchHander {
        override fun compare(a: Int, b: Int): Boolean {
            return a == b
        }
    }): Boolean {
        val csrc = src.toCharArray()
        val cdest = dest.toCharArray()
        val score = cal(csrc, 0, cdest, 0, hander).toDouble()
        val max = if (csrc.size > cdest.size) csrc.size else cdest.size
        println("最小匹配百分比：" + percent + "，成功匹配百分比：" + score / max)
        return score / max > percent
    }

    /**
     * 几个错误的字符可以接受
     * a与ab为1个字符错误可以接受
     * @param src 字符串1
     * @param dest 字符串2
     * @param hander 匹配规则
     * @return
     */
    @JvmOverloads
    fun match(errorNum: Int, src: String, dest: String, hander: MatchHander = object : MatchHander {
        override fun compare(a: Int, b: Int): Boolean {
            return a == b
        }
    }): Boolean {
        val csrc = src.toCharArray()
        val cdest = dest.toCharArray()
        val score =  cal(csrc, 0, cdest, 0, hander)
        val max = if (csrc.size > cdest.size) csrc.size else cdest.size
        println("可以接受错误数：" + errorNum + "，发现错误数：" + (max - score))
        return max - score <= errorNum
    }

    /**
     * 使用递归方法匹配字符串
     * @param csrc
     * @param i
     * @param cdest
     * @param j
     * @param hander
     * @return
     */
    private fun cal(csrc: CharArray, i: Int, cdest: CharArray, j: Int, hander: MatchHander): Int {
        var score = 0
        if (i >= csrc.size || j >= cdest.size)
            return 0
        val ismatch = hander.compare(csrc[i].toInt(), cdest[j].toInt())
        if (ismatch) {
            score++
            if (i + 1 < csrc.size && j + 1 < cdest.size)
                score += cal(csrc, i + 1, cdest, j + 1, hander)
        } else {
            var temp1 = 0
            var temp2 = 0
            var temp3 = 0
            temp1 += cal(csrc, i, cdest, j + 1, hander)
            temp2 += cal(csrc, i + 1, cdest, j, hander)
            temp3 += cal(csrc, i + 1, cdest, j + 1, hander)
            val temp4 = Math.max(temp1, temp2)
            score += Math.max(temp3, temp4)
        }
        return score
    }
}